package edu.pitt.dbmi.odie.gapp.gwt.client.analysis;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.DataSource;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.data.fields.DataSourceTextField;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.DSDataFormat;
import com.smartgwt.client.types.FormLayoutType;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.events.ResizedEvent;
import com.smartgwt.client.widgets.events.ResizedHandler;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.ButtonItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
import com.smartgwt.client.widgets.form.fields.SpinnerItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.RecordDoubleClickEvent;
import com.smartgwt.client.widgets.grid.events.RecordDoubleClickHandler;
import com.smartgwt.client.widgets.layout.VLayout;

import edu.pitt.dbmi.odie.gapp.gwt.client.dao.ODIE_DaoAnalysis;
import edu.pitt.dbmi.odie.gapp.gwt.client.util.ODIE_ClientUtils;
import edu.pitt.dbmi.odie.gapp.gwt.client.util.panel.ODIE_ButtonItemPanel;
import edu.pitt.dbmi.odie.gapp.gwt.client.util.picker.gdocs.ODIE_GDocsPickerItem;
import edu.pitt.dbmi.odie.gapp.gwt.client.util.picker.mapping.ODIE_MappingPickerItem;
import edu.pitt.dbmi.odie.gapp.gwt.client.util.picker.ontology.ODIE_OntologyPickerItem;
import edu.pitt.dbmi.odie.gapp.gwt.client.util.picker.tui.ODIE_SemanticTypePickerItem;

public class ODIE_AnalysisCreationPanel extends VLayout implements ClickHandler {

	/**
	 * Create a remote service proxy to talk to the server-side ODIE_ObaService
	 * service.
	 */
	private final ODIE_AnalysisServiceAsync analysisService = GWT
			.create(ODIE_AnalysisService.class);

	private ListGrid directoryListGrid = null;

	private final DynamicForm analysisForm = new DynamicForm();

	private ButtonItem annotateButton;

	private ODIE_GDocsPickerItem googleDocsDirItem;

	private ODIE_ProgressDisplay progressDisplay;

	private RecordDoubleClickHandler doubleClickHandler;

	private ButtonItem cancelButton;

	private boolean hasResized = false;

	public ODIE_AnalysisCreationPanel() {

		setLayoutMargin(5);
		setMembersMargin(5);

		doubleClickHandler = buildDirectoryNameRecordDoubleClickListener();

		// VLayout directoryAnnotationPanel = buildNewAnalysisGroup();
		// addMember(directoryAnnotationPanel) ;

		addMember(buildNewAnalysisForm());
		addMember(buildActionsPanel());
		progressDisplay = new ODIE_ProgressDisplay();
		addMember(progressDisplay);
		addMember(new Canvas());
	}

	private VLayout buildNewAnalysisGroup() {

		VLayout directoryAnnotationPanel = new VLayout();
		directoryAnnotationPanel.setTop(10);
		directoryAnnotationPanel.setLeft(10);
		directoryAnnotationPanel.setRight(10);
		directoryAnnotationPanel.setBottom(10);
		directoryAnnotationPanel.setMembersMargin(10);

		VLayout directoryListPanel = buildDirectoryListPanel();
		directoryAnnotationPanel.addMember(directoryListPanel);

		// actionForm = buildActionsPanel();
		// directoryAnnotationPanel.addMember(actionForm);

		return directoryAnnotationPanel;
	}

	private void appendRadioGroupItem(ArrayList<FormItem> formItemList,
			String nameAndTitle, String defaultValue, boolean isEndRow) {
		RadioGroupItem radioGroupItem = new RadioGroupItem();
		radioGroupItem.setEndRow(isEndRow);
		radioGroupItem.setVertical(true);
		radioGroupItem.setTitle(nameAndTitle);
		radioGroupItem.setName(nameAndTitle);
		radioGroupItem.setValueMap("true", "false");
		radioGroupItem.setDefaultValue(defaultValue);
		formItemList.add(radioGroupItem);
	}

	private void appendTextItem(ArrayList<FormItem> formItemList,
			String nameAndTitle, String defaultValue, boolean isEndRow) {
		TextItem textItem = new TextItem();
		textItem.setEndRow(isEndRow);
		textItem.setTitle(nameAndTitle);
		textItem.setName(nameAndTitle);
		textItem.setValue(defaultValue);
		formItemList.add(textItem);
	}

	private VLayout buildNewAnalysisForm() {

		analysisForm.setWidth("100%");
		analysisForm.setHeight("100%");

		analysisForm.setColWidths("10%", "40%", "10%", "40%");
		analysisForm.setNumCols(4);

		ArrayList<FormItem> formItemList = new ArrayList<FormItem>();
		
		ODIE_OntologyPickerItem localOntologyIDsItem = new ODIE_OntologyPickerItem();
		String nameAndTitle = "localOntologyIDs";
		localOntologyIDsItem.setTitle(nameAndTitle);
		localOntologyIDsItem.setName(nameAndTitle);
		localOntologyIDsItem.setEndRow(false);
//		localOntologyIDsItem.setColSpan(2);
		// localOntologyIDsItem.setWidth("50%") ;
		formItemList.add(localOntologyIDsItem);
		
		googleDocsDirItem = new ODIE_GDocsPickerItem();
		googleDocsDirItem.setTitle("googleDocsDir");
		googleDocsDirItem.setName("googleDocsDir");
		googleDocsDirItem.setEndRow(true) ;
		formItemList.add(googleDocsDirItem);

//		appendRadioGroupItem(formItemList, "longestOnly", "false", false);
//		appendRadioGroupItem(formItemList, "wholeWordOnly", "true", true);
//		appendTextItem(formItemList, "stopWords", "", true);
//		appendRadioGroupItem(formItemList, "withDefaultStopWords", "false",
//				true);
//		appendTextItem(formItemList, "minTermSize", "0", true);
//		appendRadioGroupItem(formItemList, "scored", "true", false);
//		appendRadioGroupItem(formItemList, "withSynonyms", "true", true);

		

//		TextItem localSemanticTypeIDsItem = new ODIE_SemanticTypePickerItem();
//		nameAndTitle = "localSemanticTypeIDs";
//		localSemanticTypeIDsItem.setTitle(nameAndTitle);
//		localSemanticTypeIDsItem.setName(nameAndTitle);
//		localSemanticTypeIDsItem.setEndRow(true);
//		localSemanticTypeIDsItem.setColSpan(2);
//		// localSemanticTypeIDsItem.setWidth("50%") ;
//		formItemList.add(localSemanticTypeIDsItem);
//
//		SpinnerItem levelMinItem = new SpinnerItem();
//		nameAndTitle = "levelMin";
//		levelMinItem.setTitle(nameAndTitle);
//		levelMinItem.setName(nameAndTitle);
//		levelMinItem.setDefaultValue(0);
//		levelMinItem.setMin(0);
//		levelMinItem.setMax(15);
//		levelMinItem.setStep(1);
//		formItemList.add(levelMinItem);
//
//		SpinnerItem levelMaxItem = new SpinnerItem();
//		nameAndTitle = "levelMax";
//		levelMaxItem.setTitle(nameAndTitle);
//		levelMaxItem.setName(nameAndTitle);
//		levelMaxItem.setDefaultValue(5);
//		levelMaxItem.setMin(0);
//		levelMaxItem.setMax(15);
//		levelMaxItem.setStep(1);
//		formItemList.add(levelMaxItem);
//
//		appendRadioGroupItem(formItemList, "activateMappings", "false", false);
//
//		ODIE_MappingPickerItem mappingItem = new ODIE_MappingPickerItem();
//		nameAndTitle = "mappingTypes";
//		mappingItem.setTitle(nameAndTitle);
//		mappingItem.setName(nameAndTitle);
//		mappingItem.setEndRow(true);
//		mappingItem.setColSpan(2);
//		// localOntologyIDsItem.setWidth("50%") ;
//		formItemList.add(mappingItem);

		

		// appendTextItem(formItemList, "googleDocsDir", "", true);

		final FormItem[] formItems = new FormItem[formItemList.size()];
		int idx = 0;
		for (FormItem formItem : formItemList) {
			formItems[idx] = formItem;
			idx++;
		}

		analysisForm.setItems(formItems);

		analysisForm.addResizedHandler(new ResizedHandler() {
			public void onResized(ResizedEvent event) {
				if (ODIE_AnalysisCreationPanel.this.hasResized) {
					analysisForm.redraw();
				} else {
					ODIE_AnalysisCreationPanel.this.hasResized = true;
				}

			}
		});

		VLayout formLayout = new VLayout();
		formLayout.setGroupTitle("Open Biomedical Annotator Settings");
		formLayout.setIsGroup(true);
		formLayout.setWidth100();
		formLayout.setHeight100();
		formLayout.setLayoutMargin(10);
		formLayout.addMember(analysisForm);
		formLayout.setOverflow(Overflow.HIDDEN);

		return formLayout;
	}

	private VLayout buildDirectoryListPanel() {

		DataSource directoriesDS = buildDirectoryDataSource();

		VLayout directoryListPanel = new VLayout();
		directoryListPanel.setTop(10);
		directoryListPanel.setLeft(10);
		directoryListPanel.setRight(10);
		directoryListPanel.setBottom(10);
		directoryListPanel.setMembersMargin(10);
		directoryListPanel.setIsGroup(true);
		directoryListPanel.setGroupTitle("Directories");

		this.directoryListGrid = ODIE_ClientUtils.buildListGrid();
		this.directoryListGrid.setDataSource(directoriesDS);
		this.directoryListGrid.addRecordDoubleClickHandler(doubleClickHandler);
		this.directoryListGrid.setAutoFetchData(true);
		this.directoryListGrid.setCanEdit(false);
		directoryListPanel.addMember(this.directoryListGrid);

		return directoryListPanel;
	}

	public DynamicForm buildActionsPanel() {
		this.annotateButton = ODIE_ClientUtils
				.buildButtonItem("Annotate", this);
		this.cancelButton = ODIE_ClientUtils.buildButtonItem("Cancel", this);
		ArrayList<ButtonItem> buttons = new ArrayList<ButtonItem>();
		buttons.add(this.annotateButton);
		buttons.add(this.cancelButton);
		return new ODIE_ButtonItemPanel("Actions", buttons);
	}

	public DynamicForm buildButtonGroup(String title,
			List<ButtonItem> buttonItems) {

		DynamicForm form = new DynamicForm();

		form.setGroupTitle(title);
		form.setIsGroup(true);

		form.setCellBorder(0);
		form.setCellPadding(2);
		form.setCellSpacing(0);
		form.setAlign(Alignment.CENTER);
		form.setMinColWidth(1);
		form.setFixedColWidths(false);
		form.setTitleWidth(0);
		form.setItemLayout(FormLayoutType.TABLE);
		form.setNumCols(buttonItems.size());
		form.setWidth100();
		form.setColWidths(150);

		if (buttonItems.size() > 0) {
			ButtonItem[] buttonItemArray = new ButtonItem[buttonItems.size()];
			int idx = 0;
			for (ButtonItem b : buttonItems) {
				buttonItemArray[idx] = b;
			}
			form.setItems(buttonItemArray);
		}

		return form;

	}

	private DataSource buildDirectoryDataSource() {
		DataSource dataSource = new DataSource();
		dataSource.setDataFormat(DSDataFormat.XML);
		dataSource.setRecordXPath("//atom:entry");
		dataSource.setDataURL("odie_client/document");
		DataSourceTextField idField = new DataSourceTextField("id", "id");
		idField.setHidden(true);
		DataSourceTextField displayLabelField = new DataSourceTextField(
				"title", "Title");
		displayLabelField.setTitle(null);
		dataSource.setFields(idField, displayLabelField);
		return dataSource;
	}

	private RecordDoubleClickHandler buildDirectoryNameRecordDoubleClickListener() {
		return new RecordDoubleClickHandler() {
			public void onRecordDoubleClick(RecordDoubleClickEvent event) {
				Record record = event.getRecord();
				String directoryHandle = record.getAttribute("id");
				String title = record.getAttribute("title");
				createAnalysis(directoryHandle, title);
			}
		};
	}

	public void onClick(ClickEvent event) {
		FormItem formItem = event.getItem();
		if (formItem == this.annotateButton) {
			String displayedTitle = String.valueOf(this.googleDocsDirItem
					.getValue());
			if (displayedTitle != null && displayedTitle.length() > 0) {
				createAnalysis(this.googleDocsDirItem.getDirectoryHandle(),
						this.googleDocsDirItem.getTitle());
			}
		}
	}

	public void onClick2(ClickEvent event) {
		FormItem formItem = event.getItem();
		if (formItem == this.annotateButton) {
			ListGridRecord record = this.directoryListGrid.getSelectedRecord();
			String directoryHandle = record.getAttribute("id");
			String title = record.getAttribute("title");
			createAnalysis(directoryHandle, title);
		}
	}

	private Boolean booleanValueOf(FormItem formItem) {
		String valueAsString = null ;
		if (formItem != null) {
			 valueAsString = (String) formItem.getValue();
		}
		return (valueAsString != null && valueAsString.equalsIgnoreCase("true")) ? true
				: false;
	}

	private Integer integerValueOf(FormItem formItem) {
		Integer result = 0 ;
		if (formItem != null) {
			Object valueAsObject = formItem.getValue();
			if (valueAsObject != null) {
				if (valueAsObject instanceof Integer) {
					result = (Integer) result;
				} else if (valueAsObject instanceof String) {
					result = Integer.parseInt((String) valueAsObject);
				}
			}
		}
		return result;
	}

	private void scrapeAnalysisFormToDAO(ODIE_DaoAnalysis result) {
//		result.setLongestOnly(booleanValueOf(this.analysisForm
//				.getField("longestOnly")));
//		result.setWholeWordOnly(booleanValueOf(this.analysisForm
//				.getField("wholeWordOnly")));
//		result.setStopWords((String) this.analysisForm.getField("stopWords")
//				.getValue());
//		result.setWithDefaultStopWords(booleanValueOf(this.analysisForm
//				.getField("withDefaultStopWords")));
//		result.setMinTermSize(integerValueOf(this.analysisForm
//				.getField("minTermSize")));
//		result.setScored(booleanValueOf(this.analysisForm.getField("scored")));
		result.setLocalOntologyIDs((String) this.analysisForm.getField(
				"localOntologyIDs").getValue());
//		result.setLocalSemanticTypeIDs((String) this.analysisForm.getField(
//				"localSemanticTypeIDs").getValue());
//		result.setLevelMin(integerValueOf(this.analysisForm
//				.getField("levelMin")));
//		result.setLevelMax(integerValueOf(this.analysisForm
//				.getField("levelMax")));
//		result.setActivateMappings(booleanValueOf(this.analysisForm
//				.getField("activateMappings")));
//		result.setMappingTypes((String) this.analysisForm.getField(
//				"mappingTypes").getValue());
	}

	// DSRequest requestProperties = new DSRequest() ;
	// requestProperties.setShowPrompt(false) ;

	private void xFerToStaging(ODIE_DaoAnalysis result) {
		if (!result.getAnalysisStatus().equals("IDLING")) {
			scrapeAnalysisFormToDAO(result);
			stageAnalysis(result);
		}
	}

	private void xFerToCoding(ODIE_DaoAnalysis result) {
		this.progressDisplay.progress(result);
		if (!result.getAnalysisStatus().equals("IDLING")) {
			codeAnalysis(result);
		} else {
			this.progressDisplay.reset();
			enableListeners();
		}
	}

	private void disableListeners() {
		// this.directoryListGrid.disable();
		this.annotateButton.disable();
	}

	private void enableListeners() {
		// this.directoryListGrid.enable();
		this.annotateButton.enable();
	}

	public void createAnalysis(String directoryHandle, String title) {

		disableListeners();
		this.progressDisplay.reset();
		analysisService.newInstance(directoryHandle, title,
				new AsyncCallback<ODIE_DaoAnalysis>() {
					public void onFailure(Throwable error) {
						SC.say("Creation failed.");
					}

					public void onSuccess(ODIE_DaoAnalysis result) {
						xFerToStaging(result);
					}
				});
	}

	public void stageAnalysis(ODIE_DaoAnalysis odieAnalysis) {

		analysisService.process(odieAnalysis,
				new AsyncCallback<ODIE_DaoAnalysis>() {
					public void onFailure(Throwable error) {
						SC.say("Staging failed.");
					}

					public void onSuccess(ODIE_DaoAnalysis result) {
						xFerToCoding(result);
					}
				});
	}

	public void codeAnalysis(ODIE_DaoAnalysis odieAnalysis) {
		analysisService.process(odieAnalysis,
				new AsyncCallback<ODIE_DaoAnalysis>() {
					public void onFailure(Throwable error) {
						SC.say("Coding failed.");
					}

					public void onSuccess(ODIE_DaoAnalysis result) {
						xFerToCoding(result);
					}
				});
	}

}
